﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

namespace Utility.FSM
{
	public class FSMStateEvent : UnityEvent<State, Agent, object> { }

	public class DelegateState : BaseStateScript
	{
		public static DelegateState New ()
		{
			return new DelegateState ();
		}

		Dictionary<string, FSMStateEvent> signalEvents = new Dictionary<string, FSMStateEvent> ();
		public FSMStateEvent OnEnter { get; private set; } = new FSMStateEvent ();
		public FSMStateEvent OnExit { get; private set; } = new FSMStateEvent ();
		public FSMStateEvent OnArrive { get; private set; } = new FSMStateEvent ();
		public FSMStateEvent OnUpdate { get; private set; } = new FSMStateEvent ();

		public FSMStateEvent OnSignal (string signal)
		{
			FSMStateEvent e;
			if (!signalEvents.TryGetValue (signal, out e))
			{
				e = new FSMStateEvent ();
				signalEvents.Add (signal, e);
			}
			return e;
		}



		#region override
		public override void OnEnterState (State state, Agent agent, object context)
		{
			OnEnter?.Invoke (state, agent, context);
		}

		public override void OnExitState (State state, Agent agent, object context)
		{
			OnExit?.Invoke (state, agent, context);
		}

		public override void OnArriveState (State state, Agent agent, object context)
		{
			OnArrive?.Invoke (state, agent, context);
		}

		public override void OnUpdateState (State state, Agent agent, object context)
		{
			OnUpdate?.Invoke (state, agent, context);
		}

		public override bool OnSignal (string signal, State state, Agent agent, object context)
		{
			FSMStateEvent e;
			if (signalEvents.TryGetValue (signal, out e))
			{
				e.Invoke (state, agent, context);
				return true;
			}
			return false;
		}
		#endregion

		#region utility
		public DelegateState SetDefaultSubstate (string defaultSubState)
		{
			OnArrive.AddListener ((State state, Agent agent, object context) =>
			{
				agent.EnterState (defaultSubState, context);
			});
			return this;
		}
		#endregion
	}
}